﻿/******************************************************************************
    myBoard is a port of MacOS X dashboard application for windows.
    Copyright (C) 2007,2008  by Yann ALET
    Email : yann.alet@gmail.com

    myBoard is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    myBoard is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
****************************************************************************/

using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows.Data;
using System.Diagnostics;
using Guide.External;
using System.Windows.Shapes;
using myBoard.Framework;
using System.IO;
using System.Reflection;
using System.Windows;
using System.Windows.Threading;
using System.Globalization;
using System.Windows.Media;

namespace Guide.XMLTV
{
    public class Guide : INotifyPropertyChanged
    {
        // Fields
        private Channels _channels;
        private List<string> _detectedCategories;
        private string _programXmlFile;
        private BackgroundWorker _refreshWorker = new BackgroundWorker();
        private string _workingPath;

        // Events
        public event PropertyChangedEventHandler PropertyChanged;

        public event OnRefreshCompleted RefreshCompleted;

        // Methods
        public Guide()
        {
            this._refreshWorker.DoWork += new DoWorkEventHandler(this._refreshWorker_DoWork);
            this._refreshWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(this._refreshWorker_RunWorkerCompleted);
        }

        private void _refreshWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            string str = System.IO.Path.Combine(this._workingPath, ".xmltv");
            this.CopyEmbededResourceOnDisk("xmltv.exe", this._workingPath);
            this.CopyEmbededResourceOnDisk("xmltv.dtd", this._workingPath);
            Process process = new Process();
            try
            {
                process.StartInfo.FileName = this._workingPath + @"\xmltv.exe";
                process.StartInfo.Arguments = new xmltvUpdateCommands()[(GrabbersEnum)e.Argument];
                process.StartInfo.WorkingDirectory = this._workingPath;
                process.StartInfo.CreateNoWindow = false;
                process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
                process.StartInfo.UseShellExecute = true;
                process.Start();
                process.WaitForExit();
                e.Result = e.Argument;
            }
            catch (Win32Exception exception)
            {
                ExceptionsManager.LogException("myGuide", exception, true);
            }
        }

        private void _refreshWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (this.RefreshCompleted != null)
            {
                this.RefreshCompleted((GrabbersEnum)e.Result);
            }
        }

        private void CopyEmbededResourceOnDisk(string resource, string path)
        {
            if (!File.Exists(System.IO.Path.Combine(path, resource)))
            {
                if (!Directory.Exists(path))
                {
                    Directory.CreateDirectory(path);
                }
                int count = 0;
                byte[] buffer = new byte[0x800];
                Assembly executingAssembly = Assembly.GetExecutingAssembly();
                using (Stream stream = executingAssembly.GetManifestResourceStream(string.Format("{0}.{1}.{2}", executingAssembly.GetName().Name, "External", resource)))
                {
                    using (FileStream stream2 = new FileStream(path + @"\" + resource, FileMode.Create, FileAccess.Write))
                    {
                        using (BinaryWriter writer = new BinaryWriter(stream2))
                        {
                            while ((count = stream.Read(buffer, 0, buffer.Length)) > 0)
                            {
                                writer.Write(buffer, 0, count);
                                writer.Flush();
                            }
                        }
                    }
                }
                buffer = null;
            }
        }

        internal void Refresh(GrabbersEnum grabber)
        {
            this._refreshWorker.RunWorkerAsync(grabber);
        }

        private void xmlLoaderBW_DoWork(object sender, DoWorkEventArgs e)
        {
            this._channels = new Channels();
            this._channels.Clear();
            if (File.Exists(this._programXmlFile))
            {
                XmlDocument document = new XmlDocument();
                document.Load(this._programXmlFile);
                foreach (XmlNode node in document.ChildNodes[2].ChildNodes)
                {
                    if (node.Name == "channel")
                    {
                        this._channels.Add(new Channel(node));
                    }
                }
                foreach (XmlNode node in document.ChildNodes[2].ChildNodes)
                {
                    if (node.Name == "programme")
                    {
                        Program p = new Program(node);
                        if (this._channels.ContainsKey(p.ChannelId))
                        {
                            this._channels.AddProgramToChannel(p.ChannelId, p);
                        }
                    }
                }
            }
        }

        private void xmlLoaderBW_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            this._detectedCategories = new List<string>();
            foreach (Channel channel in this._channels)
            {
                foreach (Program program in channel.Programs)
                {
                    if (program.Categories != null)
                    {
                        foreach (string str in program.Categories)
                        {
                            if (!this._detectedCategories.Contains(str))
                            {
                                this._detectedCategories.Add(str);
                            }
                        }
                    }
                }
            }
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs("DetectedCategories"));
            }
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs("Channels"));
            }
        }

        // Properties
        public Channels Channels
        {
            get
            {
                return this._channels;
            }
            set
            {
                this._channels = value;
            }
        }

        public List<string> DetectedCategories
        {
            get
            {
                return this._detectedCategories;
            }
            set
            {
                this._detectedCategories = value;
            }
        }

        public string ProgramXmlFile
        {
            get
            {
                return this._programXmlFile;
            }
            set
            {
                this._programXmlFile = value;
                if (!string.IsNullOrEmpty(value))
                {
                    BackgroundWorker worker = new BackgroundWorker();
                    worker.DoWork += new DoWorkEventHandler(this.xmlLoaderBW_DoWork);
                    worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(this.xmlLoaderBW_RunWorkerCompleted);
                    worker.RunWorkerAsync();
                }
            }
        }

        internal string WorkingPath
        {
            get
            {
                return this._workingPath;
            }
            set
            {
                this._workingPath = value;
            }
        }

        // Nested Types
        public delegate void OnRefreshCompleted(GrabbersEnum grabber);

    }

    public class ChannelIDValueConvertor : IValueConverter
    {
        #region IValueConverter Members

        // Methods
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (((value != null) && (value is Program)) && (((Program)value).ChannelId != null))
            {
                string channelId = ((Program)value).ChannelId;
                if ((Instances.Guide.Channels != null) && Instances.Guide.Channels.ContainsKey(channelId))
                {
                    return Instances.Guide.Channels.GetChannel(channelId).Name;
                }
                return channelId;
            }
            return string.Empty;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return null;
        }


        #endregion
    }

    public class ColorValueConvertor : IValueConverter
    {
        #region IValueConverter Members

        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if (System.Convert.ToBoolean(value))
                return "Yes";
            else
                return "No";
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            return null;
        }

        #endregion
    }

    public class RatingsVisibilityValueConvertor : IValueConverter
    {
        #region IValueConverter Members

        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if(value==null)
                return System.Windows.Visibility.Collapsed;
            else
                return System.Windows.Visibility.Visible;
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }

        #endregion
    }

    public class CategoriesVisibilityValueConvertor : IValueConverter
    {
        #region IValueConverter Members

        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if(value==null)
                return System.Windows.Visibility.Collapsed;
            else
                return System.Windows.Visibility.Visible;
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }

        #endregion
    }

    public class PresentersVisibilityValueConvertor : IValueConverter
    {
        #region IValueConverter Members

        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if (value != null && ((Credits)value).Presenter != null && ((Credits)value).Presenter.Count>0)
                return System.Windows.Visibility.Visible;
            else
                return System.Windows.Visibility.Collapsed;
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }

        #endregion
    }

    public class DescriptionVisibilityValueConvertor : IValueConverter
    {
        #region IValueConverter Members

        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if (value == null)
                return System.Windows.Visibility.Collapsed;
            else
                return System.Windows.Visibility.Visible;
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }

        #endregion
    }

    public class SubtitleVisibilityValueConvertor : IValueConverter
    {
        #region IValueConverter Members

        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if (value == null)
                return System.Windows.Visibility.Collapsed;
            else
                return System.Windows.Visibility.Visible;
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }

        #endregion
    }

    public class LengthVisibilityValueConvertor : IValueConverter
    {
        #region IValueConverter Members

        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if (System.Convert.ToInt32(value) == 0)
                return System.Windows.Visibility.Collapsed;
            else
                return System.Windows.Visibility.Visible;
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }

        #endregion
    }

    public class YearVisibilityValueConvertor : IValueConverter
    {
        #region IValueConverter Members

        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if (System.Convert.ToInt32(value) == 1)
                return System.Windows.Visibility.Collapsed;
            else
                return System.Windows.Visibility.Visible;
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }

        #endregion
    }

    public class FormatVisibilityValueConvertor : IValueConverter
    {
        #region IValueConverter Members

        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if (value != null && !string.IsNullOrEmpty(((Video)value).Format))
                return System.Windows.Visibility.Visible;
            else
                return System.Windows.Visibility.Collapsed;
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }

        #endregion
    }

    public class ColorVisibilityValueConvertor : IValueConverter
    {
        #region IValueConverter Members

        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if (value != null && ((Video)value).InColor)
                return System.Windows.Visibility.Visible;
            else
                return System.Windows.Visibility.Collapsed;
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }

        #endregion
    }

    public class ActorsVisibilityValueConvertor : IValueConverter
    {
        #region IValueConverter Members

        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if (value != null && ((Credits)value).Actors != null && ((Credits)value).Actors.Count>0)
                return System.Windows.Visibility.Visible;
            else
                return System.Windows.Visibility.Collapsed;
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }

        #endregion
    }

    public class WritersVisibilityValueConvertor : IValueConverter
    {
        #region IValueConverter Members

        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if (value != null && ((Credits)value).Writer != null && ((Credits)value).Writer.Count>0)
                return System.Windows.Visibility.Visible;
            else
                return System.Windows.Visibility.Collapsed;
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }

        #endregion
    }

    public class DirectorVisibilityValueConvertor : IValueConverter
    {
        #region IValueConverter Members

        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if (value != null && ((Credits)value).Director != null)
                return System.Windows.Visibility.Visible;
            else
                return System.Windows.Visibility.Collapsed;
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotImplementedException();
        }

        #endregion
    }

    public class CategoryColorValueConvertor : IValueConverter
    {
        // Methods
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (!string.IsNullOrEmpty(value as string))
            {
                switch (value.ToString().ToLower())
                {
                    case "film":
                    case "téléfilm":
                    case "tvfilm":
                    case "court-métrage":
                    case "drama":
                        return Instances.AllResources.GetCategoryBrush("RedBrush");

                    case "information":
                    case "journal":
                    case "news and current affairs":
                    case "business":
                    case "nieuws":
                    case "actua":
                        return Instances.AllResources.GetCategoryBrush("BlueBrush");

                    case "magazine":
                    case "current affairs":
                    case "cookery":
                        return Instances.AllResources.GetCategoryBrush("PurpleBrush");

                    case "jeu":
                    case "divertissement":
                    case "entertainment":
                    case "game show":
                    case "talkshow":
                    case "spelprogramma":
                        return Instances.AllResources.GetCategoryBrush("GreenBrush");

                    case "documentaire":
                    case "documentary":
                    case "interests":
                    case "série documentaire":
                        return Instances.AllResources.GetCategoryBrush("YellowBrush");

                    case "emission jeunesse":
                    case "children":
                    case "kinderprogramma":
                        return Instances.AllResources.GetCategoryBrush("PinkBrush");

                    case "musique":
                    case "music and arts":
                    case "muziek":
                        return Instances.AllResources.GetCategoryBrush("DarkPurpleBrush");

                    case "sport":
                    case "sportif":
                    case "voetbal":
                        return Instances.AllResources.GetCategoryBrush("LightBlueBrush");

                    case "feuilleton":
                    case "série":
                    case "serie":
                    case "soap":
                    case "familieserie":
                        return Instances.AllResources.GetCategoryBrush("OrangeBrush");
                }
            }
            return new DrawingBrush();
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }

    public class ChannelLogoSourceConvertor : IValueConverter
    {
        // Methods
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (((Instances.Guide != null) && (Instances.Guide.Channels != null)) && (value != null))
            {
                foreach (Channel channel in Instances.Guide.Channels)
                {
                    if (channel.Id == value.ToString())
                    {
                        return channel.IconUrl;
                    }
                }
            }
            return null;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }

    public class ChannelNameVisibilityConvertor : IValueConverter
    {
        // Methods
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (((Instances.Guide != null) && (Instances.Guide.Channels != null)) && (value != null))
            {
                foreach (Channel channel in Instances.Guide.Channels)
                {
                    if (!((!(channel.Id == value.ToString()) || (channel.IconUrl == null)) || string.IsNullOrEmpty(channel.IconUrl)))
                    {
                        return Visibility.Collapsed;
                    }
                }
            }
            return Visibility.Visible;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }


}
